package com.tools.scanner.ui.qrcode.scanner

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.ImageView
import androidx.annotation.IdRes
import com.bumptech.glide.Glide
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.google.mlkit.vision.barcode.common.Barcode
import com.tools.scanner.BaseFragment
import com.tools.scanner.R
import com.tools.scanner.bean.BarcodeSchema
import com.tools.scanner.bean.CalendarData
import com.tools.scanner.bean.ContactData
import com.tools.scanner.bean.EmailData
import com.tools.scanner.bean.GeoData
import com.tools.scanner.bean.PhoneData
import com.tools.scanner.bean.SmsData
import com.tools.scanner.bean.TextData
import com.tools.scanner.bean.UrlData
import com.tools.scanner.bean.WiFiData
import com.tools.scanner.database.QrHistory
import com.tools.scanner.gson.ContactDeserializer
import java.io.Serializable

abstract class BaseScannerFragment : BaseFragment() {

    companion object {
        private const val SCANNER_SCHEMA = "scanner_schema"
        private const val SCANNER_DATA = "scanner_data"
        private const val PHOTO_PATH = "photo_path"

        fun newInstance(qrHistory: QrHistory): BaseScannerFragment {
            val schema = qrHistory.schema
            val data = qrHistory.formatContent

            val bundle = Bundle()
            bundle.putString(SCANNER_SCHEMA, schema.name)
            bundle.putString(SCANNER_DATA, data)
            bundle.putString(PHOTO_PATH, qrHistory.photoPath)

            val fragment: BaseScannerFragment = when (schema) {
                BarcodeSchema.CALENDER -> {
                    CalendarFragment()
                }

                BarcodeSchema.CONTACT -> {
                    ContactFragment()
                }

                BarcodeSchema.EMAIL -> {
                    EmailFragment()
                }

                BarcodeSchema.GEO -> {
                    GeoFragment()
                }

                BarcodeSchema.PHONE -> {
                    PhoneFragment()
                }

                BarcodeSchema.SMS -> {
                    SmsFragment()
                }

                BarcodeSchema.TEXT -> {
                    TextFragment()
                }

                BarcodeSchema.URL -> {
                    UrlFragment()
                }

                BarcodeSchema.WIFI -> {
                    WifiFragment()
                }

                else -> {
                    TextFragment()
                }
            }
            fragment.arguments = bundle

            return fragment
        }
    }

    private var mBarcodeSchema: BarcodeSchema? = null
    private var mDataContent: String? = null
    private var mPhotoPath: String? = null
    private var mData: Any? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        if (savedInstanceState != null) {
            savedInstanceState.getString(SCANNER_SCHEMA)?.let {
                mBarcodeSchema = BarcodeSchema.valueOf(it)
            }
            mDataContent = savedInstanceState.getString(SCANNER_DATA)
            mPhotoPath = savedInstanceState.getString(PHOTO_PATH)
        } else {
            arguments?.getString(SCANNER_SCHEMA)?.let {
                mBarcodeSchema = BarcodeSchema.valueOf(it)
            }
            mDataContent = arguments?.getString(SCANNER_DATA)
            mPhotoPath = arguments?.getString(PHOTO_PATH)
        }

        view.findViewById<ImageView>(R.id.imageView)?.let {
            Glide.with(this).load(mPhotoPath).into(it)
        }
    }

    protected fun <T : Any> getData(clazz: Class<T>): T? {
        val content = mDataContent ?: return null

        if (clazz == String::class.java) {
            return content as T
        }

        mData?.let {
            return it as T
        }

        val gson = GsonBuilder()
            .registerTypeAdapter(Barcode.ContactInfo::class.java, ContactDeserializer())
            .create()

        mData = gson.fromJson(content, clazz)
        val data = mData ?: return null
        return data as T
    }

    fun getSchema(): BarcodeSchema? {
        return this.mBarcodeSchema
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString(SCANNER_SCHEMA, mBarcodeSchema?.name)
        outState.putString(SCANNER_DATA, mDataContent)
        outState.putString(PHOTO_PATH, mPhotoPath)
    }

}